import CameraOutlined from "@ant-design/icons/CameraOutlined"
import DeleteFilled from "@ant-design/icons/DeleteFilled"
import { OptionSelection, Product, ProductVariant } from "@mallfoundry/catalog"
import * as _ from "lodash"
import * as React from "react"
import { MouseEvent, useState } from "react"
import { ImageBlobsModal } from "../store/blobs/image-blobs"
import classes from "./product-variants-images.module.scss"

interface ProductImageProps {
  url?: string;
  onClick?: (event: MouseEvent<HTMLDivElement>) => void
  onDelete?: () => void
  children?: React.ReactNode
}

function ProductImage(props: ProductImageProps) {
  const { children, url, onClick, onDelete } = props
  return (
    <div className={classes.productImage} onClick={onClick}>
      {_.isEmpty(url) && children}
      {url && <>
        <div className={classes.productImageActions}>
          <DeleteFilled onClick={e => {
            e.stopPropagation()
            if (_.isFunction(onDelete)) {
              onDelete()
            }
          }}/>
        </div>
        <img src={url} alt=""/>
      </>}
    </div>
  )
}

interface ProductVariantImagesProps {
  title?: string;
  images: string[];
  onClick?: (event: MouseEvent<HTMLDivElement>) => void
  onChange?: (images: string[]) => void;
}

function ProductVariantImages(props: ProductVariantImagesProps) {
  const { title, images, onChange, onClick } = props

  return (
    <div className={classes.productVariantImages}>
      <header>{title}</header>
      <section>
        {
          _.map(images, (image, index) =>
            <ProductImage key={image + index}
                          url={image}
                          onClick={onClick}
                          onDelete={() => {
                            if (_.isFunction(onChange)) {
                              onChange(_.filter(images, aImage => aImage !== image && !_.isEmpty(aImage)))
                            }
                          }}>
              <CameraOutlined style={{ fontSize: "24px" }}/>
              <div className={classes.emptyDescription} children={index === 0 ? "主图" : "细节图"}/>
            </ProductImage>)
        }
      </section>
    </div>
  )
}

function selectVariants(variants: ProductVariant[], selection: OptionSelection): ProductVariant[] {
  function selectionEquals(variant: ProductVariant) {
    return !_.isUndefined(_.find(variant.optionSelections,
      aSelection => aSelection.name === selection.name && aSelection.value === selection.value))
  }

  const selectedVariants = _.filter(variants, selectionEquals)
  return _.isUndefined(selectedVariants) ? [] : selectedVariants
}


function selectVariant(variants: ProductVariant[], selection: OptionSelection): ProductVariant | undefined {
  function selectionEquals(variant: ProductVariant) {
    return !_.isUndefined(_.find(variant.optionSelections,
      aSelection => aSelection.name === selection.name && aSelection.value === selection.value))
  }

  return _.find(variants, selectionEquals)
}

function selectVariantImageUrls(variants: ProductVariant[], selection: OptionSelection): string[] {
  const variant = selectVariant(variants, selection)
  return _.isUndefined(variant) ? [] : variant.imageUrls as string[]
}

function rangeImageUrls(images: string[]) {
  return _.concat(images, _.map(_.range(0, 10 - _.size(images)), num => ""))
}

interface ProductVariantsImagesProps {
  product: Product;
  onChange: (product: Product) => void;
}

export default function ProductVariantsImages(props: ProductVariantsImagesProps) {
  const { product, onChange } = props
  const firstOption = _.first(product.options)

  const [popVisible, setPopVisible] = useState(false)
  const [optionSelection, setOptionSelection] = useState(undefined as undefined | OptionSelection)

  function handleChangeProductVariantImageUrls(selection: OptionSelection, imageUrls: string[]) {
    _.forEach(selectVariants(product.variants as ProductVariant[], selection),
      variant => variant.imageUrls = [...imageUrls])
    onChange(_.assign(new Product(), product))
  }

  return (
    <div className={classes.ProductVariantsImages}>
      <ImageBlobsModal selectable
                       visible={popVisible}
                       onSelect={blobs => {
                         const newUrls = _.chain(blobs).map(({ url = "" }) => url).value()
                         if (!_.isUndefined(optionSelection)) {
                           const imageUrls = selectVariantImageUrls(product.variants as ProductVariant[], optionSelection)
                           handleChangeProductVariantImageUrls(optionSelection, _.slice(_.union(imageUrls, newUrls), 0, 10))
                         }
                         setPopVisible(false)
                       }}
                       onCancel={() => setPopVisible(false)}/>
      {firstOption && _.map(firstOption.values, value => {
        const selection = new OptionSelection()
        selection.nameId = firstOption.id
        selection.name = firstOption.name
        selection.valueId = value.id
        selection.value = value.label
        return <ProductVariantImages key={value.label}
                                     title={`${firstOption.name} - ${value.label}`}
                                     images={rangeImageUrls(selectVariantImageUrls(product.variants as ProductVariant[], selection))}
                                     onChange={images => handleChangeProductVariantImageUrls(selection, images)}
                                     onClick={event => {
                                       setOptionSelection(selection)
                                       setPopVisible(!popVisible)
                                     }}/>
      })}
    </div>
  )
}
